<!DOCTYPE HTML>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  <link rel="shortcut icon" type="image/ico" href="favicon.ico" />
  <title>SlickGrid example 9: Row reordering</title>
  <link rel="stylesheet" href="../slick.grid.css" type="text/css"/>
  <link rel="stylesheet" href="../css/smoothness/jquery-ui.css" type="text/css"/>
  <link rel="stylesheet" href="examples.css" type="text/css"/>
  <style>
    .cell-title {
      zfont-weight: bold;
    }

    .cell-effort-driven {
      text-align: center;
    }

    .cell-reorder {
      cursor: move;
      background: url("../images/drag-handle.png") no-repeat center center;
    }

    .cell-selection {
      border-right-color: silver;
      border-right-style: solid;
      background: #f5f5f5;
      color: gray;
      text-align: right;
      font-size: 10px;
    }

    .slick-row.selected .cell-selection {
      background-color: transparent; /* show default selected row background */
    }

    .recycle-bin {
      width: 120px;
      border: 1px solid gray;
      background: beige;
      padding: 4px;
      font-size: 12pt;
      font-weight: bold;
      color: black;
      text-align: center;
      -moz-border-radius: 10px;
    }

    .red {
      background: red;
    }

    .bold {
      font-weight: bold;
    }
  </style>
</head>
<body>
<div style="position:relative">
  <div style="width:600px;">
    <div class="grid-header" style="width:100%">
      <label>Santa's TODO list:</label>
    </div>
    <div id="myGrid" style="width:100%;height:500px;"></div>
  </div>
  <div class="options-panel">
    <b>Tips:</b>
    <hr/>
    <div style="padding:6px;">
      Click to select, Ctrl-click to toggle selection, Shift-click to select a range.<br/>
      Drag one or more rows by the handle to reorder.<br/>
      Drag one or more rows to the recycle bin to delete.

      <br/>
      <br/>

      <div id="dropzone" class="recycle-bin">
        Recycle Bin
      </div>
    </div>
  </div>
</div>

<script src="../lib/firebugx.js"></script>

<script src="../lib/jquery-1.12.4.min.js"></script>
<script src="../lib/jquery-ui.min.js"></script>
<script src="../lib/jquery.event.drag-2.3.0.js"></script>
<script src="../lib/jquery.event.drop-2.3.0.js"></script>
<script src="../lib/jquery.mousewheel.js"></script>

<script src="../slick.core.js"></script>
<script src="../plugins/slick.cellrangeselector.js"></script>
<script src="../plugins/slick.cellselectionmodel.js"></script>
<script src="../plugins/slick.rowselectionmodel.js"></script>
<script src="../plugins/slick.rowmovemanager.js"></script>
<script src="../slick.formatters.js"></script>
<script src="../slick.editors.js"></script>
<script src="../slick.grid.js"></script>

<script>
var grid;
var data = [];
var columns = [
  {
    id: "#",
    name: "",
    width: 40,
    behavior: "selectAndMove",
    selectable: false,
    resizable: false,
    cssClass: "cell-reorder dnd"
  },
  {
    id: "name",
    name: "Name",
    field: "name",
    width: 500,
    cssClass: "cell-title",
    editor: Slick.Editors.Text,
    validator: requiredFieldValidator
  },
  {
    id: "complete",
    name: "Complete",
    width: 60,
    cssClass: "cell-effort-driven",
    field: "complete",
    cannotTriggerInsert: true,
    formatter: Slick.Formatters.Checkmark,
    editor: Slick.Editors.Checkbox
  },
  {
    id: "name1",
    name: "Name1",
    field: "name1",
    width: 50,
    cssClass: "cell-title",
    editor: Slick.Editors.Text,
    validator: requiredFieldValidator
  },
  {
    id: "name2",
    name: "Name2",
    field: "name2",
    width: 50,
    cssClass: "cell-title",
    editor: Slick.Editors.Text,
    validator: requiredFieldValidator
  },
  {
    id: "name3",
    name: "Name3",
    field: "name3",
    width: 50,
    cssClass: "cell-title",
    editor: Slick.Editors.Text,
    validator: requiredFieldValidator
  },
  {
    id: "name4",
    name: "Name4",
    field: "name4",
    width: 50,
    cssClass: "cell-title",
    editor: Slick.Editors.Text,
    validator: requiredFieldValidator
  }
];

var options = {
  editable: true,
  enableAddRow: true,
  enableRowReordering: true,
  enableCellNavigation: true,
  forceFitColumns: true,
  autoEdit: false,
  frozenColumn: 2
};

function requiredFieldValidator(value) {
  if (value == null || value == undefined || !value.length) {
    return {valid: false, msg: "This is a required field"};
  } else {
    return {valid: true, msg: null};
  }
}

$(function () {
  data = [
    { name: "Make a list", complete: true},
    { name: "Check it twice", complete: false},
    { name: "Find out who's naughty", complete: false},
    { name: "Find out who's nice", complete: false}
  ];

  grid = new Slick.Grid("#myGrid", data, columns, options);

  grid.setSelectionModel(new Slick.RowSelectionModel());

  var moveRowsPlugin = new Slick.RowMoveManager();

  moveRowsPlugin.onBeforeMoveRows.subscribe(function (e, data) {
    for (var i = 0; i < data.rows.length; i++) {
      // no point in moving before or after itself
      if (data.rows[i] == data.insertBefore || data.rows[i] == data.insertBefore - 1) {
        e.stopPropagation();
        return false;
      }
    }
    return true;
  });

  moveRowsPlugin.onMoveRows.subscribe(function (e, args) {
    var extractedRows = [], left, right;
    var rows = args.rows;
    var insertBefore = args.insertBefore;
    left = data.slice(0, insertBefore);
    right = data.slice(insertBefore, data.length);

    rows.sort(function (a, b) {
      return a - b;
    });

    for (var i = 0; i < rows.length; i++) {
      extractedRows.push(data[rows[i]]);
    }

    rows.reverse();

    for (var i = 0; i < rows.length; i++) {
      var row = rows[i];
      if (row < insertBefore) {
        left.splice(row, 1);
      } else {
        right.splice(row - insertBefore, 1);
      }
    }

    data = left.concat(extractedRows.concat(right));

    var selectedRows = [];
    for (var i = 0; i < rows.length; i++)
      selectedRows.push(left.length + i);

    grid.resetActiveCell();
    grid.setData(data);
    grid.setSelectedRows(selectedRows);
    grid.render();
  });

  grid.registerPlugin(moveRowsPlugin);

  grid.onDragInit.subscribe(function (e, dd) {
    // prevent the grid from cancelling drag'n'drop by default
    e.stopImmediatePropagation();
  });

  grid.onDragStart.subscribe(function (e, dd) {
    var cell = grid.getCellFromEvent(e);
    if (!cell) {
      return;
    }

    dd.row = cell.row;
    if (!data[dd.row]) {
      return;
    }

    if (Slick.GlobalEditorLock.isActive()) {
      return;
    }

    e.stopImmediatePropagation();
    dd.mode = "recycle";

    var selectedRows = grid.getSelectedRows();

    if (!selectedRows.length || $.inArray(dd.row, selectedRows) == -1) {
      selectedRows = [dd.row];
      grid.setSelectedRows(selectedRows);
    }

    dd.rows = selectedRows;
    dd.count = selectedRows.length;

    var proxy = $("<span></span>")
      .css({
        position: "absolute",
        display: "inline-block",
        padding: "4px 10px",
        background: "#e0e0e0",
        border: "1px solid gray",
        "z-index": 99999,
        "-moz-border-radius": "8px",
        "-moz-box-shadow": "2px 2px 6px silver"
      })
      .text("Drag to Recycle Bin to delete " + dd.count + " selected row(s)")
      .appendTo("body");

    dd.helper = proxy;

    $(dd.available).css("background", "pink");

    return proxy;
  });

  grid.onDrag.subscribe(function (e, dd) {
    if (dd.mode != "recycle") {
      return;
    }
    e.stopImmediatePropagation();
    dd.helper.css({top: e.pageY + 5, left: e.pageX + 5});
  });

  grid.onDragEnd.subscribe(function (e, dd) {
    if (dd.mode != "recycle") {
      return;
    }
    e.stopImmediatePropagation();
    dd.helper.remove();
    $(dd.available).css("background", "beige");
  });

  $.drop({mode: "mouse"});
  $("#dropzone")
    .bind("dropstart", function (e, dd) {
      $(this).css("background", "yellow");
    })
    .bind("dropend", function (e, dd) {
      $(dd.available).css("background", "pink");
    })
    .bind("drop", function (e, dd) {
      var rowsToDelete = dd.rows.sort().reverse();
      for (var i = 0; i < rowsToDelete.length; i++) {
        data.splice(rowsToDelete[i], 1);
      }
      grid.invalidate();
      grid.setSelectedRows([]);
    });


  grid.onAddNewRow.subscribe(function (e, args) {
    var item = {name: "New task", complete: false};
    $.extend(item, args.item);
    data.push(item);
    grid.invalidateRows([data.length - 1]);
    grid.updateRowCount();
    grid.render();
  });
})
</script>
</body>
</html>
